﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using JsGame;
using Microsoft.Xna.Framework;

namespace JsEditor
{
    public partial class JsObjEditor : TableLayoutPanel
    {
        private JsObj curObj;

        public JsObj CurObj
        {
            get { return curObj; }
            set
            {
                curObj = value;
                if (curObj != null)
                {
                    if (curObj.GetType() != ObjType)
                    {
                        SetObjType(curObj.GetType());
                    }
                }
                UpdateValue();
            }
        }
        
        public void SetObjAndType(JsObj obj,JsVar[] var_types)
        {
            curObj = obj;
            if (curObj != null)
            {
                ObjType = curObj.GetType();
                if (this.var_types != var_types)
                {
                    this.var_types = var_types;
                    Init();
                }
            }
            UpdateValue();
        }

        private JsVar[] var_types;
        private Type ObjType;
        private bool innerEventActive = true;
        private int flag50_index = -1;

        public void SetObjType(Type type)
        {
            if (ObjType != type)
            {
                ObjType = type;
                if (ObjType == typeof(JsScene))
                {
                    var_types = JsScene.types;
                }
                else if (ObjType == typeof(JsSceneEvent))
                {
                    var_types = JsSceneEvent.types;
                }
                else if (ObjType == typeof(JsNPC))
                {
                    var_types = JsNPC.types;
                }
                else if (ObjType == typeof(JsItem))
                {
                    var_types = JsItem.types;
                }
                else if (ObjType == typeof(JsSkill))
                {
                    var_types = JsSkill.types;
                }
                else if (ObjType == typeof(JsShop))
                {
                    var_types = JsShop.types;
                }
                else if (ObjType == typeof(JsSuit))
                {
                    var_types = JsSuit.types;
                }
                else 
                    var_types=null;
                Init();
            }
        }

        public JsObjEditor()
        {
            InitializeComponent();
            ColumnCount = 2;
            ColumnStyles.Clear();
            ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 72));
            ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            curObj = null;
        }

        public delegate object OnGetObjCallback(JsObjEditor sender,JsVar var_type,ushort idx);
        public delegate Image OnGetImageCallback(JsObjEditor sender, int idx);
        public delegate void OnOpenDialogCallback(JsObjEditor sender, JsVar var_type, Control control, Object old_value);
        public delegate void OnObjChangedCallback(JsObjEditor sender, JsObj cur_obj);
        

        public event OnGetObjCallback OnGetObj;
        public event OnGetImageCallback OnGetImage;
        public event OnOpenDialogCallback OnOpenDialog;
        public event OnObjChangedCallback OnObjChanged;
       
        

        private void Init()
        {
            SuspendLayout();
            Controls.Clear();
            if(var_types!=null)
            {
                TableLayoutPanelCellPosition pos = new TableLayoutPanelCellPosition();
                flag50_index = -1;
                //==================添加编辑控件==================
                if (var_types != null && var_types.Length > 0)
                {
                    RowCount = var_types.Length + 1;
                    RowStyles.Clear();
                    for (int i = 0; i < RowCount; i++)
                        RowStyles.Add(new RowStyle(SizeType.AutoSize));
                    pos.Row = 0;
                    for (int i = 0; i < var_types.Length;i++ )
                    {
                        var t = var_types[i];
                        //左侧标签
                        if (t.type != JsVarType.hidden && t.desc != null)
                        {
                            Label l = new Label();
                            l.Text = t.desc;
                            l.TextAlign = ContentAlignment.MiddleLeft;
                            //l.MaximumSize = new Size(64,0);
                            l.Dock = DockStyle.Fill;
                            l.AutoSize = true;
                            Controls.Add(l);
                            pos.Column = 0;
                            SetCellPosition(l, pos);
                        }
                        //右侧编辑控件
                        if (t.type == JsVarType.int16 || t.type == JsVarType.uint16)
                        {
                            if ((t.flag & JsVar.FlagEvent50_Mask) != 0)
                            {
                                JsVar50 cb = new JsVar50();
                                cb.MaxValue = t.max;
                                cb.MinValue = t.min;
                                cb.OnValueChanged += new EventHandler(Editor_ValueChanged);
                                cb.Tag = pos.Row;
                                Controls.Add(cb);
                                pos.Column = 1;
                                SetCellPosition(cb, pos);
                            }
                            else if ((t.flag & JsVar.FlagAllowNoChange) != 0)
                            {
                                JsVar50 cb = new JsVar50();
                                cb.CheckBoxName = "不改变";
                                cb.MaxValue = t.max;
                                cb.MinValue = t.min;
                                cb.OnValueChanged += new EventHandler(Editor_ValueChanged);
                                cb.Tag = pos.Row;
                                Controls.Add(cb);
                                pos.Column = 1;
                                SetCellPosition(cb, pos);
                            }
                            else
                            {
                                NumericUpDown cb = new NumericUpDown();
                                cb.Width = 100;
                                cb.Minimum = t.min;
                                cb.Maximum = t.max;
                                cb.ValueChanged += new EventHandler(Editor_ValueChanged);
                                cb.Tag = pos.Row;
                                Controls.Add(cb);
                                pos.Column = 1;
                                SetCellPosition(cb, pos);
                            }

                        }
                        else if (t.type == JsVarType.str)
                        {
                            TextBox cb = new TextBox();
                            cb.MaxLength = t.max;
                            cb.TextChanged += new EventHandler(Editor_ValueChanged);
                            if (t.max > 8)
                            {
                                cb.Multiline = true;
                                cb.Height = 36;
                            }
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_readonly)
                        {
                            TextBox cb = new TextBox();
                            cb.Width = 128;
                            cb.ReadOnly = true;
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.boolean)
                        {
                            CheckBox cb = new CheckBox();
                            cb.CheckedChanged += new EventHandler(Editor_ValueChanged);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_list || 
                            t.type == JsVarType.js_type )
                        {
                            ComboBox cb = new ComboBox();
                            cb.DropDownStyle = ComboBoxStyle.DropDownList;
                            cb.SelectionChangeCommitted += new EventHandler(Editor_ValueChanged);
                            cb.Items.AddRange(t.fields);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_cmd50)
                        {
                            ComboBox cb = new ComboBox();
                            cb.DropDownStyle = ComboBoxStyle.DropDownList;
                            cb.Items.AddRange(JsEventType.Event50TypeList);
                            cb.SelectionChangeCommitted += new EventHandler(Editor_ValueChanged);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_pic)
                        {
                            JsPicPicker cb = new JsPicPicker();
                            cb.Height = 96;
                            cb.OnPicPick += new EventHandler(Editor_ValueChanged);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_pos)
                        {
                            TextBox cb = new TextBox();
                            cb.ReadOnly = true;
                            cb.Click += new EventHandler(Editor_ValueChanged);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_talk ||
                                    t.type == JsVarType.js_task ||
                                    t.type == JsVarType.js_item ||
                                    t.type == JsVarType.js_npc ||
                                    t.type == JsVarType.js_event ||
                                    t.type == JsVarType.js_scene ||
                                    t.type == JsVarType.js_skill)
                        {
                            TextBox cb = new TextBox();
                            cb.ReadOnly = true;
                            if (t.type == JsVarType.js_talk || t.type == JsVarType.js_task)
                            {
                                cb.Multiline = true;
                                cb.Height = 128;
                            }
                            cb.Click += new EventHandler(Editor_ValueChanged);
                            cb.Tag = pos.Row;
                            Controls.Add(cb);
                            pos.Column = 1;
                            SetCellPosition(cb, pos);
                        }
                        else if (t.type == JsVarType.js_flag50)
                        {
                            flag50_index = i;
                        }
                        //var control=GetControlFromPosition(pos.Column, pos.Row);
                        //if (control != null)
                        //{
                        //    control.Dock = DockStyle.Fill;
                        //}
                        pos.Row++;
                    }
                }
            }
            ResumeLayout();
            AutoScrollPosition = System.Drawing.Point.Empty;
            Visible = false;

        } //function

        private void UpdateValue()
        {
            if (curObj != null && var_types!=null)
            {
                for (int i = 0; i < curObj.values.Length; i++)
                    UpdateRowValue(i);                
                Visible = true;
            }
            else
            {
                Visible = false;
            }
        }

        private void UpdateRowValue(int i)
        {
            JsVar t = var_types[i];
            if (t.type == JsVarType.int16 || t.type == JsVarType.uint16)
            {
                if((t.flag&JsVar.FlagEvent50_Mask)!=0)
                {
                    JsVar50 cb = (JsVar50)GetControlFromPosition(1, i);
                    if (cb != null)
                    {
                        if (flag50_index >= 0 && flag50_index < curObj.values.Length)
                        {
                            int flag = curObj.values[flag50_index];
                            cb.Checked = (flag & (t.flag & JsVar.FlagEvent50_Mask)) != 0;
                        }
                        else
                            cb.Checked = false;
                        innerEventActive = false;
                        cb.Value = curObj.values[i];
                        innerEventActive = true;
                    }
                }
                else if ((t.flag & JsVar.FlagAllowNoChange) != 0)
                {
                    JsVar50 cb = (JsVar50)GetControlFromPosition(1, i);
                    if(cb!=null)
                    {
                        if(curObj.values[i]==0xfffe)
                        {
                            
                            cb.MaxValue = 0xfffe;
                            cb.MinValue = 0xfffe;
                            cb.Checked = true;
                            cb.ReadOnly = true;
                            innerEventActive = false;
                            cb.Value = 0xfffe;
                            innerEventActive = true;
                        }
                        else
                        {
                            cb.MinValue = t.min;
                            cb.MaxValue = t.max;
                            cb.Checked = false;
                            cb.ReadOnly = false;
                            innerEventActive = false;
                            if (t.type == JsVarType.int16)
                                cb.Value = (short)curObj.values[i];
                            else
                                cb.Value = curObj.values[i];
                            innerEventActive = true;
                        }
                    }
                }
                else
                {
                    NumericUpDown tb = (NumericUpDown)GetControlFromPosition(1, i);
                    if (tb != null)
                    {
                        innerEventActive = false;
                        if (t.type == JsVarType.int16)
                              tb.Value = (short)curObj.values[i];
                        else
                            tb.Value = curObj.values[i];
                        innerEventActive = true;
                    }
                }
            }

            else if (t.type == JsVarType.str)
            {
                TextBox tb = (TextBox)GetControlFromPosition(1, i);
                if (tb != null)
                {
                    innerEventActive = false;
                    tb.Text = curObj.GetString(i, t.max);
                    innerEventActive = true;
                }
            }
            else if (t.type == JsVarType.js_readonly)
            {
                TextBox tb = (TextBox)GetControlFromPosition(1, i);
                if (tb != null)
                {
                    innerEventActive = false;
                    tb.Text = curObj.values[i].ToString();
                    innerEventActive = true;
                }
            }
            else if (t.type == JsVarType.boolean)
            {
                CheckBox cb = (CheckBox)GetControlFromPosition(1, i);
                if (cb != null)
                { 
                    innerEventActive = false;
                    cb.Checked = (curObj.values[i] != 0);
                    innerEventActive = true;
                }
            }
            else if (t.type == JsVarType.js_list ||
                     t.type == JsVarType.js_type)
            {
                ComboBox cb = (ComboBox)GetControlFromPosition(1, i);
                if (cb != null)
                {
                    innerEventActive = false;
                    int value = -1;
                    if (t.fields!=null)
                    for(int j=0;j<t.fields.Length;j++)
                        if (curObj.values[i] == t.fields[j].value)
                        {
                            value = j;
                            break;
                        }
                    cb.SelectedIndex = value;
                    innerEventActive = true;
                }
            }
            else if (t.type == JsVarType.js_cmd50)
            {
                ComboBox cb = (ComboBox)GetControlFromPosition(1, i);
                if (cb != null)
                {
                    var type = JsEventType.GetEvent50Type(curObj.values[i]);
                    if (type != null)
                    {
                        if (var_types != type.types)
                        {
                            SetObjAndType(curObj, type.types);
                        }
                    }
                    innerEventActive = false;
                    cb.SelectedItem = type;
                    innerEventActive = true;
                }
            }
            else if (t.type == JsVarType.js_pic)
            {
                JsPicPicker pb = (JsPicPicker)GetControlFromPosition(1, i);
                if (pb != null)
                {
                    if (OnGetImage != null && curObj.values[i] != 0)
                    {
                        pb.Image = OnGetImage(this, curObj.values[i] / 2);
                    }
                    else
                        pb.Image = null;
                    pb.Text = curObj.values[i].ToString();
                }
            }
            else if (t.type == JsVarType.js_pos)
            {
                TextBox tb = (TextBox)GetControlFromPosition(1, i);
                if (tb != null)
                {
                    var p = curObj.GetPos(i, t.min);
                    tb.Text = p.X.ToString() + "," + p.Y.ToString();
                }
            }
            else if (t.type == JsVarType.js_item ||
                     t.type == JsVarType.js_npc ||
                     t.type == JsVarType.js_skill ||
                     t.type == JsVarType.js_talk ||
                     t.type == JsVarType.js_task ||
                     t.type == JsVarType.js_event ||
                     t.type == JsVarType.js_scene)
            {
                TextBox cb = (TextBox)GetControlFromPosition(1, i);
                if (cb != null)
                {
                    if (OnGetObj != null)
                    {
                        var obj = OnGetObj(this, t, curObj.values[i]);
                        if (obj != null)
                            cb.Text = obj.ToString();
                        else
                            cb.Text = "";
                    }
                }
            }
        }


        private void Editor_ValueChanged(Object sender, EventArgs e)
        {
            if (!innerEventActive) return;
                if (var_types != null && curObj != null)
                {
                    int idx = (int)((Control)sender).Tag;
                    JsVar t = var_types[idx];
                    if (t.type == JsVarType.int16 || t.type == JsVarType.uint16)
                    {
                        if((t.flag&JsVar.FlagEvent50_Mask)!=0)
                        {
                            JsVar50 cb = (JsVar50)sender;
                            if (flag50_index >= 0 && flag50_index < curObj.values.Length)
                            {
                                int flag = curObj.values[flag50_index];
                                if (cb.Checked)
                                {
                                    flag = flag ^ ( t.flag & JsVar.FlagEvent50_Mask);
                                    cb.MaxValue = 0xffff;
                                    cb.MinValue = 0;
                                }
                                else
                                {
                                    flag = flag & (~( t.flag & JsVar.FlagEvent50_Mask));
                                    cb.MaxValue = t.max;
                                    cb.MinValue = t.min;
                                }
                                curObj.values[flag50_index] = (ushort)flag;
                            }                      
                            curObj.values[idx] = (ushort)cb.Value;
                            if (OnObjChanged != null) OnObjChanged(this, curObj);
                        }
                        else if((t.flag&JsVar.FlagAllowNoChange)!=0)
                        {
                            JsVar50 cb = (JsVar50)sender;
                            if (cb.Checked)
                            {
                                cb.MaxValue = 0xfffe;
                                cb.MinValue = 0xfffe;
                                cb.Value = 0xfffe;
                                cb.ReadOnly = true;
                            }
                            else
                            {
                                cb.MaxValue = t.max;
                                cb.MinValue = t.min;
                                cb.ReadOnly = false;
                            }
                            curObj.values[idx] = (ushort)(cb.Value);
                            if (OnObjChanged != null) OnObjChanged(this, curObj);
                        }
                        else
                        {
                            NumericUpDown tb = (NumericUpDown)sender;
                            curObj.values[idx] = (ushort)Decimal.ToInt16(tb.Value);
                            if(OnObjChanged!=null) OnObjChanged(this,curObj);
                        }

                    }
                    else if (t.type == JsVarType.boolean)
                    {
                        CheckBox cb = (CheckBox)sender;
                        curObj.values[idx] = (ushort)(cb.Checked ? 1 : 0);
                        if (OnObjChanged != null) OnObjChanged(this, curObj);
                    }
                    else if (t.type == JsVarType.js_list ||
                        t.type == JsVarType.js_type)
                    {
                        ComboBox cb = (ComboBox)sender;
                        if (t.fields!=null && cb.SelectedIndex>=0&&cb.SelectedIndex<t.fields.Length)
                            curObj.values[idx] = t.fields[cb.SelectedIndex].value;
                        else
                            curObj.values[idx] = 0;
                        if (OnObjChanged != null) OnObjChanged(this, curObj);
                    }
                    else if (t.type == JsVarType.js_cmd50)
                    {
                        ComboBox cb = (ComboBox)sender;
                        JsEventType type = cb.SelectedItem as JsEventType;
                        curObj.values[(int)cb.Tag] = type.cmd;
                        SetObjAndType(curObj, type.types);
                        if (OnObjChanged != null) OnObjChanged(this, curObj);
                    }
                    else if (t.type == JsVarType.str)
                    {
                        TextBox cb = (TextBox)sender;
                        curObj.SetString(cb.Text, (int)cb.Tag, t.max);
                        if (OnObjChanged != null) OnObjChanged(this, curObj);
                    }
                    else if (t.type == JsVarType.js_talk ||
                                t.type == JsVarType.js_task ||
                                t.type == JsVarType.js_item ||
                                t.type == JsVarType.js_npc ||
                                t.type == JsVarType.js_event ||
                                t.type == JsVarType.js_scene ||
                                t.type == JsVarType.js_skill)
                    {
                        if (OnOpenDialog != null)
                             OnOpenDialog(this, t, (Control)sender, curObj.values[idx]);
                    }
                    
                    else if (t.type == JsVarType.js_pic)
                    {
                        if ((t.flag & JsVar.FlagAllowNoChange) != 0)
                        {
                            var result = MessageBox.Show(this, "请确认是否更改", "是否更改", MessageBoxButtons.YesNoCancel);
                            if (result == DialogResult.Yes)
                            {
                                if (OnOpenDialog != null)
                                    OnOpenDialog(this, t, (Control)sender, curObj.values[idx]);
                            }
                            else if (result == DialogResult.No)
                            {
                                curObj.values[idx] = 0xfffe;
                                ((JsPicPicker)sender).Text="65534";
                                if (OnObjChanged != null) OnObjChanged(this, curObj);
                            }
                        }
                        else
                            if (OnOpenDialog != null)
                                OnOpenDialog(this, t, (Control)sender, curObj.values[idx]);
                    }
                    else if (t.type == JsVarType.js_pos)
                    {
                        if ((t.flag & JsVar.FlagAllowNoChange) != 0)
                        {
                            var result = MessageBox.Show(this, "请确认是否更改", "是否更改", MessageBoxButtons.YesNoCancel);
                            if (result == DialogResult.Yes)
                            {
                                if (OnOpenDialog != null)
                                        OnOpenDialog(this, t, (Control)sender, curObj.GetJsPos(idx, t));
                            }
                            else if (result == DialogResult.No)
                            {
                                curObj.values[idx] = 0xfffe;
                                curObj.values[idx + t.min] = 0xfffe;
                                ((TextBox)sender).Text = "65534,65534";
                                if (OnObjChanged != null) OnObjChanged(this, curObj);
                            }
                        }
                        else
                            if (OnOpenDialog != null)
                                OnOpenDialog(this, t, (Control)sender, curObj.GetJsPos(idx, t));
                    }
                }

        }

        public void SetValue(int idx,ushort value)
        {
            if (curObj != null && idx >= 0 && idx < curObj.values.Length)
            {
                curObj.values[idx] = value;
                UpdateRowValue(idx);
            }
        }

        public void SetValue(int idx, int x, int y)
        {
            if (curObj != null && idx >= 0 && idx < curObj.values.Length)
            {
                JsVar t = var_types[idx];
                if (t.type == JsVarType.js_pos)
                {
                    curObj.SetPos(idx, x, y, t.min);
                    UpdateRowValue(idx);
                }
            }
        }

        public void SetValue(int idx,  Microsoft.Xna.Framework.Point pos)
        {
            if (curObj != null && idx >= 0 && idx < curObj.values.Length)
            {
                JsVar t = var_types[idx];
                if (t.type == JsVarType.js_pos)
                {
                    curObj.SetPos(idx, pos.X,pos.Y,t.min);
                    UpdateRowValue(idx);
                }
            }
        }

        public void TriggerControl(Control control)
        {
            Editor_ValueChanged(control, EventArgs.Empty);
        }

    } //class
}  //namesapce
